package ai.people.netmon.framework.domain.graph;

import com.people.core.validator.annotation.GraphTagValue;
import com.people.core.validator.annotation.NumberStatusValue;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * 前端图格式
 *
 * @author zhenglin
 * @date 2022/4/24
 */
@Data
@NoArgsConstructor
public class FrontGraphBase {
    /**
     * 节点
     */
    @Size(min = 1, message = "节点数量不能为0")
    @Valid
    Set<Node> nodes;
    /**
     * 边
     */
    @Valid
    Set<Edge> edges;

    @Data
    public static class Node {
        /**
         * id
         */
        @NotBlank(message = "节点id不能为空")
        private String id;
        /**
         * 自定义属性
         */
        @Valid
        private LabelCfg labelCfg;

        /**
         * 坐标轴x
         */
        private Double x;

        /**
         * 坐标轴y
         */
        private Double y;

        @Data
        public static class LabelCfg {
            /**
             * 节点类型 nodesType=1：档案主体，nodesType=2： 触角，nodesType=3：副主体
             * 查询详情时默认返回为null
             *
             * @mock 1
             */
            @NumberStatusValue(values = {1, 2, 3}, message = "节点类型值非法")
            private Integer nodesType;
            /**
             * 标签名
             *
             * @mock company
             */
            @Valid
            private Value tagCode;
            /**
             * 属性
             */
            private Map<String, Object> properties;

        }

        @Data
        @AllArgsConstructor
        @NoArgsConstructor
        public static class Value {
            /**
             * 标签代码
             *
             * @mock person_archives
             */
            @NotBlank(message = "标签编码不能为空")
            @GraphTagValue
            private String code;
            /**
             * 标签名
             */
            private String name;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            Node node = (Node) o;
            return Objects.equals(id, node.id) && Objects.equals(labelCfg, node.labelCfg);
        }

        @Override
        public int hashCode() {
            return Objects.hash(id, labelCfg);
        }
    }

    @Data
    public static class Edge {
        /**
         * 出边node id
         */
        @NotBlank(message = "source id不能为空")
        private String source;
        /**
         * 入边node id
         */
        @NotBlank(message = "target id不能为空")
        private String target;
        /**
         * 箭头指向
         */
        private Style style;
        /**
         * 自定义属性
         */
        @Valid
        private LabelCfg labelCfg;

        @Data
        public static class LabelCfg {
            /**
             * 边类型
             */
            private String type;
            /**
             * 边code
             */
            @Valid
            private Value edgeCode;
        }

        @Data
        public static class Style {
            /**
             * 开始箭头
             */
            @NotNull(message = "开始节点的箭头不能为空")
            private Boolean startArrow;
            /**
             * 结束箭头
             */
            @NotNull(message = "结束节点的箭头不能为空")
            private Boolean endArrow;
        }

        @Data
        @AllArgsConstructor
        @NoArgsConstructor
        public static class Value {
            /**
             * 边代码
             *
             * @mock family
             */
//            @GraphEdgeValue
            private String code;
            /**
             * 边名字
             */
            private String name;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            Edge edge = (Edge) o;
            return (Objects.equals(source, edge.source) || Objects.equals(target, edge.source)) &&
                    (Objects.equals(target, edge.target) || Objects.equals(source, edge.target)) &&
                    Objects.equals(labelCfg, edge.labelCfg);
        }

        @Override
        public int hashCode() {
            return Objects.hash(source, target, labelCfg) + Objects.hash(target, source, labelCfg);
        }
    }
}
